package services

import (
    "fmt"
    "sync"
    "time"
    "volux/utils"
)

type QoSManager struct {
    mu              sync.RWMutex
    qosSettings     map[string]*QoSSettings   // key: subsystem NQN
    qosStats        map[string]*QoSStats      // 实时统计
    updateInterval  time.Duration
    spdkClient      *utils.SPDKClient
}

type QoSSettings struct {
    MaxIOPS       int64  `json:"max_iops"`
    MaxBW         int64  `json:"max_bw"`        // MB/s
    MaxQueueDepth int    `json:"max_queue_depth"`
    RWBalance     int    `json:"rw_balance"`    // 读写比例 0-100
    BurstSize     int64  `json:"burst_size"`    // IOPS突发大小
    BurstTime     int    `json:"burst_time"`    // 突发允许时间(秒)
}

type QoSStats struct {
    CurrentIOPS     int64     `json:"current_iops"`
    CurrentBW       int64     `json:"current_bw"`       // MB/s
    CurrentQD       int       `json:"current_qd"`
    ReadPercent     float64   `json:"read_percent"`
    LastUpdate      time.Time `json:"last_update"`
    BurstStartTime  time.Time `json:"burst_start_time"`
    InBurst         bool      `json:"in_burst"`
}

func NewQoSManager(spdkClient *utils.SPDKClient) *QoSManager {
    qm := &QoSManager{
        qosSettings:    make(map[string]*QoSSettings),
        qosStats:       make(map[string]*QoSStats),
        updateInterval: time.Second * 1,
        spdkClient:     spdkClient,
    }
    
    go qm.monitor()
    return qm
}

// UpdateQoS 动态更新QoS设置
func (qm *QoSManager) UpdateQoS(nqn string, settings *QoSSettings) error {
    qm.mu.Lock()
    defer qm.mu.Unlock()

    // 检查是否处于突发状态
    if stats, exists := qm.qosStats[nqn]; exists && stats.InBurst {
        // 等待突发结束再更新
        return nil
    }

    // 更新SPDK设置
    err := qm.spdkClient.SetSubsystemQoS(nqn, map[string]interface{}{
        "max_iops": settings.MaxIOPS,
        "max_bw": settings.MaxBW * 1024 * 1024,
        "max_queue_depth": settings.MaxQueueDepth,
        "rw_balance": settings.RWBalance,
    })

    if err != nil {
        return err
    }

    qm.qosSettings[nqn] = settings
    return nil
}

// monitor 持续监控QoS状态
func (qm *QoSManager) monitor() {
    ticker := time.NewTicker(qm.updateInterval)
    for range ticker.C {
        qm.mu.Lock()
        for nqn, settings := range qm.qosSettings {
            // 调用 GetSubsystemStats 时去除 nqn 参数
            stats, err := qm.spdkClient.GetSubsystemStats()
            if err != nil {
                continue
            }

            // 更新统计信息
            qm.updateStats(nqn, settings, stats)
            
            // 检查是否需要突发处理
            qm.handleBurst(nqn, settings)
        }
        qm.mu.Unlock()
    }
}

// updateStats 更新统计信息
func (qm *QoSManager) updateStats(nqn string, settings *QoSSettings, stats interface{}) {
    statsMap := stats.(map[string]interface{})
    
    qosStats := &QoSStats{
        CurrentIOPS: int64(statsMap["iops"].(float64)),
        CurrentBW:   int64(statsMap["bandwidth"].(float64)) / (1024 * 1024), // 转换为MB/s
        CurrentQD:   int(statsMap["queue_depth"].(float64)),
        ReadPercent: statsMap["read_percent"].(float64),
        LastUpdate:  time.Now(),
    }

    qm.qosStats[nqn] = qosStats
}

// handleBurst 处理突发情况
func (qm *QoSManager) handleBurst(nqn string, settings *QoSSettings) {
    stats := qm.qosStats[nqn]
    
    // 检查是否需要进入突发模式
    if stats.CurrentIOPS > settings.MaxIOPS {
        if (!stats.InBurst) {
            stats.InBurst = true
            stats.BurstStartTime = time.Now()
            
            // 临时提高限制
            qm.spdkClient.SetSubsystemQoS(nqn, map[string]interface{}{
                "max_iops": settings.MaxIOPS + settings.BurstSize,
            })
        } else {
            // 检查突发时间是否结束
            if time.Since(stats.BurstStartTime) > time.Duration(settings.BurstTime)*time.Second {
                stats.InBurst = false
                
                // 恢复正常限制
                qm.spdkClient.SetSubsystemQoS(nqn, map[string]interface{}{
                    "max_iops": settings.MaxIOPS,
                })
            }
        }
    }
}

// GetQoSStats 获取QoS统计信息
func (qm *QoSManager) GetQoSStats(nqn string) (*QoSStats, error) {
    qm.mu.RLock()
    defer qm.mu.RUnlock()
    
    stats, exists := qm.qosStats[nqn]
    if (!exists) {
        return nil, fmt.Errorf("no QoS stats for subsystem: %s", nqn)
    }
    return stats, nil
}

func (qm *QoSManager) collectQoS() {
    // ...existing code or移除此函数体...
}
